package com.autonavi.yunda.yunji.controller.forward;

import com.autonavi.yunda.yunji.common.utils.JsonUtils;
import com.autonavi.yunda.yunji.core.enums.OperationRecordType;
import com.autonavi.yunda.yunji.service.BucUserService;
import com.autonavi.yunda.yunji.service.OperationRecordService;
import com.autonavi.yunda.yunji.service.ProjectAuthService;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.*;

@Slf4j
@RestController
@RequestMapping(value = "xxl-job-admin")
public class YunSchedulerAdminForwardController {

    private static final String HTTP_POST = "POST";
    private static final String HTTP_GET = "GET";
    OkHttpClient client = new OkHttpClient();

    @Value("${yunji.scheduler-admin.host}")
    private String schedulerHost;

    @Resource
    private BucUserService bucUserService;

    @Resource
    private OperationRecordService operationRecordService;

    @Resource
    ProjectAuthService projectAuthService;

    @RequestMapping(value = "/**")
    public Object forward(HttpServletRequest request) throws Exception {
        String method = request.getMethod();
        String apiURI = request.getRequestURI();
        String result = "";

        List<String> projectIds = null;
        if(apiURI.contains("pageList")) {
            projectIds = projectAuthService.listAuthorizedProjectIds();
        }
        request.getRequestURL().toString();
        Request.Builder requestBuilder = new Request.Builder()
                .url(schedulerHost + apiURI + "?" + request.getQueryString() + (CollectionUtils.isEmpty(projectIds) ? "" : "&projectIds=" + String.join(",",projectIds)));

        if (HTTP_POST.equals(method)) {
            MediaType mediaType = MediaType.parse(request.getContentType());
            RequestBody body = RequestBody.create(mediaType, getRequestBodyAsString(request));
            requestBuilder.post(body);
        } else if (HTTP_GET.equals(method)) {
            requestBuilder.get();
        }
        // 复制请求头
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            String headerValue = request.getHeader(headerName);
            requestBuilder.header(headerName, headerValue);
        }


        requestBuilder
                .addHeader("Content-Type", "application/json;charset=UTF-8")
                .addHeader("Accept-Charset", "application/json;charset=UTF-8");
        requestBuilder.removeHeader("Accept-Encoding");
        Request httpRequest = requestBuilder.build();
        Response response = client.newCall(httpRequest).execute();
        result = response.body().string();

        if(StringUtils.isNotEmpty(result)) {
            Map returnMap = JsonUtils.from(result, Map.class);
            if(returnMap.get("code") == null || 200 != ((Integer) returnMap.get("code"))) {
                return JsonUtils.from(result, Object.class);
            }
            if(returnMap.get("content") != null && returnMap.get("content") instanceof String) {
                addOperationRecord(apiURI,(String)returnMap.get("content"));
            }
        }
        return JsonUtils.from(result, Object.class);
    }

    private String getRequestBodyAsString(HttpServletRequest request) throws IOException {
        StringBuilder stringBuilder = new StringBuilder();
        BufferedReader reader = request.getReader();
        String line;
        while ((line = reader.readLine()) != null) {
            stringBuilder.append(line);
        }
        return stringBuilder.toString();
    }

    private void addOperationRecord(String apiURI,String jobInfoId) {
        if(!apiURI.contains("xxl-job-admin/jobinfo")) {
            return;
        }
        String[] split = apiURI.split("/");
        String operation = split[split.length-1];
        Optional<OperationRecordType.JobInfoType> first = Arrays.stream(OperationRecordType.JobInfoType.values())
                .filter(type -> type.getOperation().equals(operation))
                .findFirst();
        if(first.isPresent()) {
            operationRecordService.add(first.get(), jobInfoId);
        }
    }
}
